package com.liuwei.spring.cloud.framework.validation;

import com.liuwei.spring.cloud.common.utils.StringPool;
import jakarta.validation.*;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
import java.util.stream.Collectors;

/**
 * @author : evan.liu
 * @version V1.0
 * @Description: 对象验证工具类
 * @date Date : 2022年04月03日 8:08 下午
 */

public class Validator {

    /**
     * 根据默认框架验证参数的有效性(默认一般为HibernateValidate)
     * @param obj
     * @param <T>
     * @throws IllegalArgumentException
     */
    public static<T> void validate(T obj) throws IllegalArgumentException{
        if(ObjectUtils.isEmpty(obj)){
            return;
        }
        ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory();
        jakarta.validation.Validator validator = validatorFactory.getValidator();
        Set<ConstraintViolation<T>> validateResult = validator.validate(obj);
        buildValidateMessage(validateResult,true);
    }

    /**
     * 校验这个Bean上 某个具体的属性
     * @param obj
     * @param <T>
     * @param <R>
     */
    public static<T,R> void validateProperty(T obj, String propertyName){
        if(ObjectUtils.isEmpty(obj)){
            return;
        }
        ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory();
        jakarta.validation.Validator validator = validatorFactory.getValidator();
        Set<ConstraintViolation<T>> validateResult = validator.validateProperty(obj,propertyName);
        buildValidateMessage(validateResult,true);
    }

    private static<T> String buildValidateMessage(Set<ConstraintViolation<T>> validateResult, boolean throwIfViolation){
        if(CollectionUtils.isEmpty(validateResult)) {
            return StringPool.EMPTY;
        }
        List<String> msg = validateResult.stream().map(x->{
            String notice = "";
            String template = x.getMessageTemplate();
            if(!template.isEmpty() && template.startsWith(StringPool.LEFT_BRACE) && template.endsWith(StringPool.RIGHT_BRACE)){
                notice = x.getPropertyPath() + StringPool.SPACE +x.getMessage();
            }else{
                notice = x.getMessageTemplate();
            }
            return notice;
        }).collect(Collectors.toList());
        if(throwIfViolation){
            throw new ValidationException(String.join(StringPool.SEMICOLON,msg));
        }else{
            return String.join(StringPool.SEMICOLON,msg);
        }
    }

    /**
     * 清除掉所有特殊字符 (保留.)
     * @param str
     * @return
     * @throws PatternSyntaxException
     */
    public static String filterString(String str) throws PatternSyntaxException {
        if(StringUtils.isEmpty(str)){
            return str;
        }
        // 只允许字母和数字 // String regEx ="[^a-zA-Z0-9]";
        //String regEx="[`~!@#$%^&*()+=|{}':;',\\[\\].<>/?~！@#￥%……&*（）——+|{}【】‘；：”“’。，、？]";
        String regEx="[`~!@#$%^&*()+=|{}':;',\\[\\]_<>/?~！@#￥%……&*（）——+|{}【】‘；：”“’。，、？]";
        Pattern p = Pattern.compile(regEx);
        Matcher m = p.matcher(str);
        return m.replaceAll("").trim();
    }

    /**
     * 判断表达式为 True
     * @param expression 判断表达式
     * @param errMessage 错误信息
     */
    public static void isTrue(boolean expression, String errMessage) {
        if (!expression) {
            throw new ValidationException(errMessage);
        }
    }

    /**
     * 判断表达式为 True
     * @param expression 表达式
     * @param exception 自定义异常
     * @param <T> 异常类型
     */
    public static<T extends RuntimeException> void isTrue(boolean expression, T exception) {
        if (!expression) {
            throw exception;
        }
    }

    /**
     * 判断对象为非空
     * @param object 目标对象
     * @param errMessage 错误信息
     */
    public static void notNull(Object object, String errMessage) {
        if (ObjectUtils.isEmpty(object)) {
            throw new ValidationException(errMessage);
        }
    }

    /**
     * 判断集合非空
     * @param collection 集合
     * @param errMessage 错误信息
     */
    public static void notEmpty(Collection<?> collection, String errMessage) {
        if (CollectionUtils.isEmpty(collection)) {
            throw new ValidationException(errMessage);
        }
    }

    /**
     * 判断 Map 非空
     * @param map 目标数据
     * @param errMessage 错误信息
     */
    public static void notEmpty(Map<?, ?> map, String errMessage) {
        if (MapUtils.isEmpty(map)) {
            throw new ValidationException(errMessage);
        }
    }

    /**
     * 判断 Array 非空
     * @param array 目标数组
     * @param msg 错误信息
     */
    public static void notEmpty(Object[] array,String msg){
        if (ArrayUtils.isEmpty(array)) {
            throw new ValidationException(msg);
        }
    }


    /**
     * 判断目标文本是否匹配正则表达式
     * @param regex 正则表达式
     * @param value 目标文本
     * @return 是否
     */
    public static boolean regex(String regex,String value) {
        Pattern p = Pattern.compile(regex);
        return p.matcher(value).matches();
    }
}
